package com.atguigu.aiproject.service.impl;

import com.atguigu.aiproject.constant.RedisKeyConstant;
import com.atguigu.aiproject.exception.BusinessException;
import com.atguigu.aiproject.mapper.UserMapper;
import com.atguigu.aiproject.entity.User;
import com.atguigu.aiproject.service.UserService;
import com.atguigu.aiproject.utils.JwtUtils;
import com.atguigu.aiproject.utils.UserContext;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final Boolean imageReview;// 是否开启图片审核
    private final String filePath;// img/avator
    private final JwtUtils jwtUtils;
    private final RedisTemplate<String, Object> redisTemplate;

    public UserServiceImpl(@Value("${system.enable_image_review}") Boolean imageReview,
                           @Value("${system.avatar_save_path}") String filePath,
                           JwtUtils jwtUtils,
                           RedisTemplate<String, Object> redisTemplate
    ) {
        this.imageReview = imageReview;
        this.filePath = filePath;
        this.jwtUtils = jwtUtils;
        this.redisTemplate = redisTemplate;
    }

    @Data
    public static class LoginResult {
        public User user;
        public String jwt;

        public LoginResult(User user, String jwt) {
            this.user = user;
            this.jwt = jwt;
        }
    }

    /**
     * 用户登录并实现单端登录
     */
    @Override
    public LoginResult login(String username, String password) {

        // 查询用户信息
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getLoginName, username);
        User dbUser = super.getOne(queryWrapper);

        // 验证用户
        if (dbUser == null || !password.equals(dbUser.getLoginPwd())) {
            throw new BusinessException("用户名或密码错误");
        }

        // 生成JWT令牌，包含用户ID、用户名和设备指纹
        Map<String, Object> claims = new HashMap<>();
        claims.put("username", username);
        claims.put("userId", dbUser.getId());
        String jwt = jwtUtils.generateToken(claims);

        // 处理单端登录 - 踢掉前一个登录
        handleSingleLogin(dbUser.getId(), jwt);

        // 缓存用户信息和token关系
        cacheUserLoginInfo(dbUser, jwt);

        // 清理敏感信息
        dbUser.setLoginPwd(null);

        return new LoginResult(dbUser, jwt);
    }

    /**
     * 处理单端登录逻辑
     */
    private void handleSingleLogin(Integer userId, String newToken) {
        try {
            String userTokenKey = RedisKeyConstant.USER_JWT_KEY + userId;
            String oldToken = (String) redisTemplate.opsForValue().get(userTokenKey);

            // 如果存在旧token，删除旧token相关的缓存
            if (oldToken != null) {
                String oldTokenKey = RedisKeyConstant.JWT_USER_KEY + oldToken;
                redisTemplate.delete(oldTokenKey);
            }

            // 存储新的token关系
            redisTemplate.opsForValue().set(userTokenKey, newToken,
                    jwtUtils.getExpirationTime(newToken), TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            // Redis操作失败不影响登录流程，但单端登录功能会受影响
            log.error("单端登录失效", e);
        }
    }

    /**
     * 缓存用户登录信息
     */
    private void cacheUserLoginInfo(User user, String token) {
        try {
            String tokenKey = RedisKeyConstant.JWT_USER_KEY + token;

            // 缓存用户信息（不包含密码）
            User cacheUser = new User();
            cacheUser.setId(user.getId());
            cacheUser.setLoginName(user.getLoginName());
            // 可以添加其他需要缓存的字段

            redisTemplate.opsForValue().set(tokenKey, cacheUser,
                    jwtUtils.getExpirationTime(token), TimeUnit.MILLISECONDS);
        } catch (Exception e) {
            log.error("用户信息缓存失败", e);
        }
    }

    @Override
    public void logout(String token) {
        try {
            String tokenKey = RedisKeyConstant.JWT_USER_KEY + token;
            User user = (User) redisTemplate.opsForValue().get(tokenKey);
            if (user != null) {
                String userTokenKey = RedisKeyConstant.USER_JWT_KEY + user.getId();
                redisTemplate.delete(List.of(tokenKey, userTokenKey));// 1RTT
            }
        } catch (Exception e) {
            log.error("用户登出处理失败", e);
        }
    }

    @Override
    public User getUserInfo() {
        int userId = UserContext.getUserId();
        String userInfoKey = RedisKeyConstant.USER_INFO_KEY + userId;
        try {
            User user = (User) redisTemplate.opsForValue().get(userInfoKey);
            if (user != null) {
                return user;
            }
        }catch (Exception e){
            log.error("获取用户信息失败", e);
        }
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(User::getId, userId);
        User user = super.getOne(queryWrapper);
        // 清理敏感信息
        user.setLoginPwd(null);

        redisTemplate.opsForValue().set(userInfoKey, user, 86400 * 30, TimeUnit.SECONDS);// 缓存30天，如有修改信息应立即失效

        return user;
    }

    @Override
    public boolean deleteById(Integer id) {
        throw new BusinessException("你要寄吧干啥？");
        /*if (super.removeById(id)) {
            // 删除用户信息缓存
            String userInfoKey = RedisKeyConstant.USER_INFO_KEY + id;
            redisTemplate.delete(userInfoKey);
            return true;
        }
        return false;*/
    }

    @Override
    public String updateAvatar(MultipartFile avatar) throws IOException {
        if(Boolean.TRUE.equals(imageReview)){
            //调用审核方法
            return null;
        }
        // 检查文件是否为空
        if (avatar.isEmpty()) {
            throw new BusinessException("上传文件不能为空");
        }
        // 验证文件类型
        String contentType = avatar.getContentType();
        if (!"image/jpeg".equals(contentType) && !"image/png".equals(contentType)) {
            throw new BusinessException("上传文件类型错误");
        }
        // 保存文件到本地
        String fileName = saveFileToLocal(avatar, filePath);

        // 更新用户头像信息
        int userId = UserContext.getUserId();
        this.update(new UpdateWrapper<User>().eq("u_id", userId).set("u_avatar", fileName));
        return fileName;// 返回保存后的文件访问URL
    }
    /**
     * 保存文件到指定目录
     * @param file 要保存的文件
     * @param directoryPath 文件存储目录路径
     * @return 保存后的文件访问URL
     */
    private String saveFileToLocal(MultipartFile file, String directoryPath) throws IOException {
        // 生成唯一文件名
        String originalFilename = file.getOriginalFilename();
        String fileExtension = originalFilename.substring(originalFilename.lastIndexOf("."));
        String fileName = UUID.randomUUID() + fileExtension;

        // 确保目录存在
        File directory = new File(directoryPath);
        if (!directory.exists()) {
            directory.mkdirs();
        }
        // 保存文件到本地
        File destFile = new File(directoryPath, fileName);
        file.transferTo(new File(destFile.getAbsolutePath()));
        System.out.println("保存图片到本地目录：" + destFile.getAbsolutePath());
        // 返回访问URL
        return fileName;
    }
}
